home *** CD-ROM | disk | FTP | other *** search
-
- /* Copyright (C) 1990 Riet Oolman
-
- This file is part of GLASS.
-
- GLASS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- GLASS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GLASS; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* file: contsens.c
- author: H. Oolman
- last modified: 8-2-1991
- purpose: procedures for context-sensitive checks on Glass
- modifications: p2c translated, tmc access procs.
- */
-
- #include "handleds.h"
- #include "check.ds.h"
- #include "check.var.h"
- #include "check.afuncs.h"
- #include "errorenv.h"
- #include "unification.h"
- #include "contsens.h"
-
- Local typcrec *replacelocssome ();
-
- typedef struct typcrec * adirindic ;
- /* to inidcate if a system application should be interpreted adirectionally
- (if type APPSET) or unidirectionally (otherwise) */
-
- #define makeadirwanted BuildAPS()
- /* adirectional system application wanted */
- #define makedirwanted BuildUNKNOWN(0L,false,false)
- /* unidirectional system application wanted */
- #define makewanted(t) replacelocssome(t,true)
- /* turn type into info on what kind of system appl. is wanted */
- /* These three make an adirindic */
-
- Void splitwanted(ty, frst, scnd)
- /* split ty, which should be composed, in parts frst and scnd
- to be used in subparts of a ':' expression */
- adirindic ty, *frst, *scnd;
- { while (ty->kind == kindINDIR) ty = ty->INDIR.tcind;
- if (ty->kind == kindCT)
- { *frst = ty->CT.tcfirst;
- *scnd = ty->CT.tcrest;
- }
- else if (ty->kind == kindSOME)
- { *frst = ty->SOME.tcpart;
- *scnd = ty;
- } else { *frst = makedirwanted;
- *scnd = *frst;
- }
- }
-
- boolean adirwanted(ty)
- /* test if adirectional system application wanted */
- adirindic ty;
- { while (ty->kind == kindINDIR) ty = ty->INDIR.tcind;
- return (ty->kind == kindAPS);
- }
-
- Local typcrec *typeval PP((adirindic appnon, val vl, envrec *btns_,
- long splitlevel_));
-
- Local Void WritesymbolNoext(f, nm)
- FILE *f;
- symbol nm;
- { /* Because it is not known beforehand if errors will occur,
- all names are extended if uiq is true. But in printing
- error messages it is nicer if they are not there.
- This procedure prints a name nm without extension. */
- long i, lth;
-
- lth = nm->length;
- if (uniq) {
- while (nm->body[lth - 1] != '_' && lth > 0)
- lth--;
- lth--;
- }
- for (i = 0; i < lth; i++)
- putc(nm->body[i], f);
- }
-
- Local Void unparsfp(f, fmp)
- FILE *f;
- fp fmp;
- { /* unparses fp's */
- switch (fmp->tag) {
-
- case TAGFpComp:
- putc('(', f);
- unparsfp(f, fmp->FpComp.fpfirst);
- fprintf(f, "): ");
- unparsfp(f, fmp->FpComp.fprest);
- break;
-
- case TAGFpEmpty:
- fprintf(f, "[]");
- break;
-
- case TAGFpList:
- putc('[', f);
- fmp = fmp->FpList.fplist;
- while (fmp != NULL) {
- unparsfp(f, fmp);
- fmp = fmp->next;
- if (fmp != NULL)
- fprintf(f, ", ");
- }
- putc(']', f);
- break;
-
- case TAGFpName:
- WritesymbolNoext(f, fmp->FpName.fpsym);
- break;
-
- case TAGFpInt:
- fprint_inum(f, fmp->FpInt.fpi);
- break;
-
- case TAGFpFlo:
- fprint_fnum(f, fmp->FpFlo.fpf);
- break;
-
- case TAGFpStr:
- fprint_string(f, fmp->FpStr.fps);
- break;
-
- case TAGFpBool:
- if (fmp->FpBool.fpb)
- fprintf(f, "TRUE");
- else
- fprintf(f, "FALSE");
- break;
- }
- } /* unparsfp */
-
- /* true <-> data struct. adaptations for the use of macro
- expander the result of which is not handled by the type
- checker */
-
- Local Void unparsval(f, vl)
- FILE *f;
- val vl;
- { /* unparses (most) val's */
- long l;
- string op;
-
- switch (vl->tag) {
-
- case TAGVValApply:
- unparsval(f, vl->VValApply.avval);
- fprintf(f, " (");
- unparsval(f, vl->VValApply.avpar);
- putc(')', f);
- break;
-
- case TAGVSym:
- WritesymbolNoext(f, vl->VSym.sym);
- if (takewarning) {
- fprintf(f, "/*");
- myprint_orig(f,vl->VSym.symorig);
- fprintf(f, "*/");
- }
- break;
-
- case TAGVInt:
- fprint_inum(f,vl->VInt.i);
- break;
-
- case TAGVFlo:
- fprint_fnum(f,vl->VFlo.f);
- break;
-
- case TAGVStr:
- fprint_string(f,vl->VStr.s);
- break;
-
- case TAGVBool:
- if (vl->VBool.b)
- fprintf(f, "TRUE");
- else
- fprintf(f, "FALSE");
- break;
-
- case TAGVAtom:
- case TAGVType:
- case TAGVMacAlts:
- error(10L, NULL, NULL, Buildsymbol( "unparsval", 9L), NULL, false);
- break;
-
- case TAGVSysLambda:
- putc('%', f);
- unparsfp(f, vl->VSysLambda.slpar);
- putc('.', f);
- unparsval(f, vl->VSysLambda.slval);
- break;
-
- case TAGVSysSigma:
- putc('$', f);
- unparsfp(f, vl->VSysSigma.sspar);
- putc('.', f);
- unparsval(f, vl->VSysSigma.ssval);
- break;
-
- case TAGVSysApply:
- unparsval(f, vl->VSysApply.asval);
- fprintf(f, " (");
- unparsval(f, vl->VSysApply.aspar);
- putc(')', f);
- break;
-
- case TAGVWhere:
- unparsval(f, vl->VWhere.wval);
- fprintf(f, " Where .... Endwhere");
- break;
-
- case TAGVList:
- putc('[', f);
- vl = vl->VList.l;
- while (vl != NULL) {
- unparsval(f, vl);
- vl = vl->next;
- if (vl != NULL)
- fprintf(f, ", ");
- }
- putc(']', f);
- break;
-
- case TAGVAppset:
- putc('{', f);
- vl = vl->VAppset.aps;
- while (vl != NULL) {
- unparsval(f, vl);
- vl = vl->next;
- if (vl != NULL)
- fprintf(f, ", ");
- }
- putc('}', f);
- break;
-
- case TAGVSyn:
- fprintf(f, "*[");
- vl = vl->VSyn.synlist;
- while (vl != NULL) {
- unparsval(f, vl);
- vl = vl->next;
- if (vl != NULL)
- fprintf(f, ", ");
- }
- putc(']', f);
- break;
-
- case TAGVMacLambda:
- if (vl->VMacLambda.mval == NULL) /* !! used to pack fp */
- unparsfp(f, vl->VMacLambda.mpar);
- else {
- fprintf(f, "\\(");
- unparsfp(f, vl->VMacLambda.mpar);
- fprintf(f, ").");
- unparsval(f, vl->VMacLambda.mval);
- }
- break;
-
- case TAGVBuiltin:
- op = vl->VBuiltin.oper;
- if (cmp_string(op, "->")==0) {
- unparsval(f, vl->VBuiltin.args);
- fprintf(f, "->");
- unparsval(f, vl->VBuiltin.args->next);
- fprintf(f, "; ");
- unparsval(f, vl->VBuiltin.args->next->next);
- } else {
- if (cmp_string(op,"[]")==0) {
- unparsval(f, vl->VBuiltin.args);
- fprintf(f, " (");
- unparsval(f, vl->VBuiltin.args->next);
- putc(')', f);
- } else {
- if (cmp_string(op, "[..]")==0) {
- unparsval(f, vl->VBuiltin.args);
- fprintf(f, " @(");
- unparsval(f, vl->VBuiltin.args->next);
- fprintf(f, ")...(");
- unparsval(f, vl->VBuiltin.args->next->next);
- putc(')', f);
- } else {
- if (cmp_string(op, "+1")==0) {
- putc('+', f);
- unparsval(f, vl->VBuiltin.args);
- } else {
- if (cmp_string(op, "-1")==0) {
- putc('-', f);
- unparsval(f, vl->VBuiltin.args);
- } else {
- if (cmp_string(op, "~")==0) {
- putc('~', f);
- unparsval(f, vl->VBuiltin.args);
- } else {
- if (cmp_string(op, "itof")==0) {
- fprintf(f, "itof ");
- unparsval(f, vl->VBuiltin.args);
- } else {
- if ((cmp_string(op, "^")==0) | (cmp_string(op,":")==0)) {
- putc('(', f);
- unparsval(f, vl->VBuiltin.args);
- putc(')', f);
- fprintf(f, op);
- putc(' ', f);
- unparsval(f, vl->VBuiltin.args->next);
- } else {
- if ((cmp_string(op,"=")==0) | (cmp_string(op,"/=")==0) |
- (cmp_string(op,"<")==0) | (cmp_string(op,"<=")==0) |
- (cmp_string(op,">=")==0) | (cmp_string(op,">")==0) |
- (cmp_string(op,"*")==0) | (cmp_string(op,"/")==0) |
- (cmp_string(op,"DIV")==0) | (cmp_string(op,"MOD")==0) |
- (cmp_string(op,"&")==0) | (cmp_string(op,"|")==0) |
- (cmp_string(op,"-2")==0) | (cmp_string(op,"+2")==0)) {
- unparsval(f, vl->VBuiltin.args);
- putc(' ', f);
- if (cmp_string(op,"-2")==0)
- putc('-', f);
- else if (cmp_string(op, "+2")==0)
- putc('+', f);
- else
- fprintf(f, op);
- fprintf(f, " (");
- unparsval(f, vl->VBuiltin.args->next);
- putc(')', f);
- } else
- {l=0; while (op[l]!='\0') l++;
- error(10L, NULL, NULL, Buildsymbol(op,l), NULL, false);}
- }
- }
- }
- }
- }
- }
- }
- }
- break;
- }
- } /* unparsval */
-
- /* Local variables for convtype: */
- struct LOC_convtype {
- envrec *btns;
- orig typorig;
- symbol loctyvars, boundnames;
- } ;
-
- Local dirgraphrec *extractdirs(t)
- /* extract the directions in a systemtype. Easy for comparing */
- typ t;
- {
-
- switch (t->tag) {
-
- case TAGTypUni:
- return BuildCd(BuildOd(BuildIN()),
- BuildCd(BuildOd(BuildOUT()), BuildOd(BuildNON())));
- break;
-
- case TAGTypNon:
- return extractdirs(t->TypNon.nontyp);
- break;
-
- case TAGTypProd:
- if (t->TypProd.ptypes == NULL)
- return BuildOd(BuildNON());
- else {
- return BuildCd(extractdirs(t->TypProd.ptypes),
- extractdirs(new_TypProd(t->TypProd.ptypes->next)));
- }
- break;
-
- case TAGTypAtom:
- return BuildOd(BuildNON());
- break;
-
- case TAGTypIn:
- return BuildOd(BuildIN());
- break;
-
- case TAGTypOut:
- return BuildOd(BuildOUT());
- break;
-
- case TAGTypPwr:
- return BuildSd(extractdirs(t->TypPwr.pwrtyp),
- BuildOd(BuildNON()));
- break;
- case TAGTypStar:
- return BuildSd(extractdirs(t->TypStar.startyp),
- BuildOd(BuildNON()));
- break;
-
- case TAGTypLocal:
- return extractdirs(t->TypLocal.loctyp);
- break;
-
- case TAGTypSym:
- return BuildOd(BuildNON());
- break;
-
- case TAGTypAppset:
- case TAGTypFun:
- case TAGTypInt:
- case TAGTypFlo:
- case TAGTypBind:
- case TAGTypBool:
- case TAGTypString:
- error(8L, NULL, NULL, NULL, NULL, false);
- return BuildOd(BuildNON());
- break;
- }
- }
-
- Local Void addnumnamestoenv(e)
- /* adds names to curenv, with type INT, if not yet present;
- otherwise redirects namepointer
- e: expression in power type */
- val e;
- {
- symbol nm;
-
- switch (e->tag) {
-
- case TAGVValApply:
- addnumnamestoenv(e->VValApply.avpar);
- addnumnamestoenv(e->VValApply.avval);
- break;
-
- case TAGVSym:
- nm = e->VSym.sym;
- if (lookup(curenv, &nm) == NULL) {
- error(21L, NULL, NULL, nm, NULL, true);
- update(&curenv, nm, BuildINT());
- } else
- e->VSym.sym = nm;
- break;
-
- case TAGVInt:
- case TAGVFlo:
- case TAGVStr:
- case TAGVBool: /* ready */
- break;
-
- case TAGVList:
- e = e->VList.l;
- while (e != NULL) {
- addnumnamestoenv(e);
- e = e->next;
- }
- break;
-
- case TAGVBuiltin:
- e = e->VBuiltin.args;
- while (e != NULL) {
- addnumnamestoenv(e);
- e = e->next;
- }
- break;
-
- case TAGVType:
- case TAGVSysLambda:
- case TAGVSysSigma:
- case TAGVSysApply:
- case TAGVMacAlts:
- case TAGVMacLambda:
- case TAGVWhere:
- case TAGVAppset:
- case TAGVAtom:
- case TAGVSyn:
- error(20L, NULL, NULL, NULL, NULL, false);
- break;
- }
- } /* addnumnamestoenv */
-
- Local typcrec *conv(glty, mustconn, LINK)
- /* make tc form for glty: names replaced by
- loc.ty.var/basetype/typename,
- extract directions, listtypes to some, Prodtype to
- comp.type; also some simple checks
- mustconn: glty must be a connection type
- check if no -:n names occur more than once in glty, and if
- the expression in a power type give integers; make the int.
- names unique if uniq */
- typ glty;
- boolean mustconn;
- struct LOC_convtype *LINK;
- { /* ass.: restrictions on type (except for names) checked by parser */
- symbol n;
- typcrec *tc, *Result;
- envrec *cur;
-
- switch (glty->tag) {
-
- case TAGTypAtom:
- Result = BuildBASETY(Copysymbol(glty->TypAtom.atomnm),
- newname(),
- LINK->typorig);
- /* make glty^.atomnm point to btns: */
- n = glty->TypAtom.atomnm;
- tc = lookup(LINK->btns, &n);
- glty->TypAtom.atomnm = n;
- return Result;
- break;
-
- case TAGTypFun:
- if (glty->TypFun.funpar->tag == TAGTypBind) {
- n = glty->TypFun.funpar->TypBind.boundname;
- addunequal(n, &LINK->boundnames);
- update(&curenv, n, BuildINT());
- cur = curenv;
- tc = conv(glty->TypFun.funres, false, LINK);
- /* unbound names from $e$ in $t^e$ types found in
- funres are added to curenv */
- if (adaptds && uniq)
- addext(cur->name0, cur->uniqext);
- cur->name0 = marker;
- /* turn into marker: invisible */
- return BuildSINGLEARROW(BuildINT(), tc);
- } else
- return BuildSINGLEARROW(
- conv(glty->TypFun.funpar, false, LINK),
- conv(glty->TypFun.funres, false, LINK));
- break;
-
- case TAGTypIn:
- return conv(glty->TypIn.ityp, true, LINK);
- break;
-
- case TAGTypOut:
- return conv(glty->TypOut.otyp, true, LINK);
- break;
-
- case TAGTypUni:
- return BuildSYSTY(extractdirs(glty),
- BuildCT(conv(glty->TypUni.uityp, true, LINK),
- BuildCT(conv(glty->TypUni.uotyp, true, LINK),
- BuildSOME(BuildUNKNOWN(newname(), false, true),
- newname()))));
- break;
-
- case TAGTypNon:
- return BuildSYSTY(extractdirs(glty),
- conv(glty->TypNon.nontyp, true, LINK));
- break;
-
- case TAGTypInt:
- return BuildINT();
- break;
-
- case TAGTypBind:
- return BuildINT();
- break;
-
- case TAGTypFlo:
- return BuildFLOAT();
- break;
-
- case TAGTypString:
- return BuildSTRING();
- break;
-
- case TAGTypBool:
- return BuildBOOL();
- break;
-
- case TAGTypAppset:
- return BuildAPS();
- break;
-
- case TAGTypPwr:
- addnumnamestoenv(glty->TypPwr.pwrval);
- compat(BuildINT(),
- typeval(makedirwanted, glty->TypPwr.pwrval, NULL, 0L),
- glty->TypPwr.pwrval);
- return BuildSOME(conv(glty->TypPwr.pwrtyp, mustconn, LINK),
- newname());
- break;
-
- case TAGTypProd:
- if (glty->TypProd.ptypes == NULL) {
- return BuildSOME(BuildUNKNOWN(newname(), false,
- mustconn), newname());
- /* !! mog. foute invulling voor UNKNOWN false false */
- } else {
- return BuildCT
- (conv(glty->TypProd.ptypes, mustconn, LINK),
- conv(new_TypProd(glty->TypProd.ptypes->next),
- mustconn, LINK));
- }
- break;
-
- case TAGTypStar:
- return BuildSOME
- (conv(glty->TypStar.startyp, mustconn, LINK),
- newname());
- break;
-
- case TAGTypSym:
- n = glty->TypSym.sym;
- tc = lookup(LINK->btns, &n);
- if (tc == NULL)
- { error(1L, NULL, NULL, n, NULL, false);
- return BuildUNKNOWN(newname(), false, false);
- } else
- { glty->TypSym.sym = n; return tc;}
- break;
- }
- } /* conv */
-
- Local nminstrec *convlocs(lnames)
- /* lnames does not contain double names; in result all get inst. nr. 0 */
- symbol lnames;
- {
- nminstrec *nmi;
-
- if (lnames == NULL) return NULL;
- else {
- nmi = Buildnminstptr(lnames, 0L);
- nmi->next = convlocs(lnames->next);
- return nmi;
- }
- } /* convlocs */
-
- Local typcrec *convtype(glty, btns_, typorig_)
- /* glty: glass type to be converted to tc form (and checked for
- grammatical correctness)
- btns_: BT/TN names plus types in glty
- typorig_: orig, if glty is the typas of a DefTyp */
- typ glty;
- envrec *btns_;
- orig typorig_;
- {
- struct LOC_convtype V;
- typcrec *Result;
- symbol l1, l2, l2o;
- envrec *oce;
-
- V.typorig = typorig_;
- if (glty->tag == TAGTypLocal) {
- V.loctyvars = glty->TypLocal.locsyms;
- glty = glty->TypLocal.loctyp;
- } else
- V.loctyvars = NULL;
- l1 = NULL;
- l2 = V.loctyvars;
- mark_(&btns_);
- while (l2 != NULL) {/* remove double names from loctyvars */
- if (!isin(l2, l1)) {
- l2o = l2;
- addcopy(l2, &l1);
- update(&btns_,l2,BuildLOC(l2,0L));
- } else
- l2o->next = l2->next;
- l2 = l2->next;
- }
- V.btns = btns_;
- oce = curenv;
- curenv = NULL;
- mark_(&curenv); /* for the -: n names */
- V.boundnames = NULL; /* the -:n names */
- Result = BuildALL(convlocs(V.loctyvars),
- conv(glty, false, &V));
- while (curenv != NULL)
- release_(&curenv, adaptds && uniq);
- /* make -:n names and those in power types unique
- while loop because of names made invisible by turning into marker */
- curenv = oce;
- release_(&btns_,adaptds && uniq); /* make loc. ty.vars. unique */
- return Result;
- } /* convtype */
-
- Local envrec *extendbtns(elts, btns)
- /* btns: environment of BASETYPE/TYPE names plus tc-form of
- defining types;
- elts: list of defs, the BASETYPEs/TYPEs from which are to
- extend btns for forming the result;
- in the tc types in this btns env. names for BT/TY have been
- replaced by redirections to the defining types */
- def elts;
- envrec *btns;
- {
- def hel;
- symbol n, ens;
- typcrec *ut, *t;
- orig oo;
-
- hel = elts;
- ens = NULL;
- while (hel != NULL) {
- if (hel->tag == TAGDefVal) {
- addcopy(hel->DefVal.defval, &nestednames);
- oo = nestednorig;
- nestednorig = hel->DefVal.valorig;
- addunequal(hel->DefVal.defval, &ens);
- nestednames = nestednames->next;
- nestednorig = oo;
- } else {
- if (hel->tag == TAGDefTyp) {
- addcopy(hel->DefTyp.deftyp, &nestednames);
- oo = nestednorig;
- nestednorig = hel->DefTyp.typorig;
- addunequal(hel->DefTyp.deftyp, &ens);
- update(&btns, hel->DefTyp.deftyp,
- BuildUNKNOWN(newname(), false, false));
- /* fist put all in btns with unknown type */
- nestednames = nestednames->next;
- nestednorig = oo;
- }
- }
- hel = hel->next;
- }
- hel = elts;
- while (hel != NULL) {
- if (hel->tag == TAGDefTyp) {
- addcopy(hel->DefTyp.deftyp, &nestednames);
- oo = nestednorig;
- nestednorig = hel->DefTyp.typorig;
- t = convtype(hel->DefTyp.typas, btns, hel->DefTyp.typorig);
- n = hel->DefTyp.deftyp;
- ut = lookup(btns, &n);
- hel->DefTyp.deftyp = n; /* for unique names */
- if (occurs(ut->UNKNOWN.unknm, t))
- error(0L, NULL, NULL, n, NULL, false);
- else
- becomes(ut, t);
- /* replace the unknown type by indir. to the found one */
- nestednames = nestednames->next;
- nestednorig = oo;
- }
- hel = hel->next;
- }
- return btns;
- } /* extendbtns */
-
- Local nminstrec *wrl(lns, nr)
- nminstrec *lns;
- long nr;
- {
- /* make a copy of the list lns, with nr as inst. nr. */
- nminstrec *hn;
-
- if (lns == NULL)
- return NULL;
- else {
- hn = Buildnminstptr(lns->nm, nr);
- hn->next = wrl(lns->next, nr);
- return hn;
- }
- } /* wrl */
-
- Local Void wro(ty, inst, tyo, locnrd)
- typcrec *ty;
- long inst;
- typcrec **tyo;
- nminstrec **locnrd;
- {
- /* ty can contain nested 'ALL's (because of typenamings)
- tyo is ty with the ALLs removed (after supplying LOCs with
- an instance nr.)
- locnrd are the names from the ALLs in ty (with inst. nr.)
- inst is the instance nr. for LOCs which are not within an
- ALL (those get a different inst. nr.)
- */
- long nn;
- typcrec *t1, *t2;
- nminstrec *ln1, *ln2;
-
- *locnrd = NULL;
- while (ty->kind == kindINDIR) ty = ty->INDIR.tcind;
- switch (ty->kind) {
-
- case kindALL:
- nn = newname(); /* inst. nr. for LOCs in ALL's scope */
- wro(ty->ALL.tcall, nn, tyo, locnrd);
- Appendnminstptr(wrl(ty->ALL.locs, nn), *locnrd, locnrd);
- break;
-
- case kindLOC:
- *tyo = BuildLOC(ty->LOC.locname, inst);
- break;
-
- case kindSINGLEARROW:
- wro(ty->SINGLEARROW.tcarg, inst, &t1, &ln1);
- wro(ty->SINGLEARROW.tcres, inst, &t2, &ln2);
- Appendnminstptr(ln2, ln1, locnrd);
- *tyo = BuildSINGLEARROW(t1, t2);
- break;
-
- case kindAPS:
- case kindINT:
- case kindBOOL:
- case kindSTRING:
- case kindFLOAT:
- case kindBASETY:
- *tyo = ty;
- break;
-
- case kindSYSTY:
- wro(ty->SYSTY.syscomp, inst, &t1, locnrd);
- *tyo = BuildSYSTY(ty->SYSTY.sysdirs, t1);
- break;
-
- case kindEMPTYT:
- *tyo = ty;
- break;
-
- case kindCT:
- wro(ty->CT.tcfirst, inst, &t1, &ln1);
- wro(ty->CT.tcrest, inst, &t2, &ln2);
- *tyo = BuildCT(t1, t2);
- Appendnminstptr(ln2, ln1, locnrd);
- break;
-
- case kindUNKNOWN:
- *tyo = BuildUNKNOWN(newname(), ty->UNKNOWN.mustendemp,
- ty->UNKNOWN.mustconn);
- break;
-
- case kindSOME:
- wro(ty->SOME.tcpart, inst, &t1, locnrd);
- *tyo = BuildSOME(t1, newname());
- break;
-
- }
- } /* wro */
-
- Local Void satistyp(t, mustconn, mustendemp)
- typcrec *t;
- boolean mustconn, mustendemp;
- {
- /* checks that after replacing names by named type/ loctyvar/
- basetype the result t is syntactically correct */
- if ((((1L << ((long)t->kind)) &
- ((1L << ((long)kindAPS)) | (1L << ((long)kindSINGLEARROW)) |
- (1L << ((long)kindSYSTY)) | (1L << ((long)kindINT)) |
- (1L << ((long)kindFLOAT)) | (1L << ((long)kindSTRING)) |
- (1L << ((long)kindBOOL)))) != 0 &&
- (mustconn || mustendemp)) ||
- (((1L << ((long)t->kind)) & ((1L << ((long)kindLOC)) |
- (1L << ((long)kindBASETY)))) !=0 && mustendemp)) {
- /* << used for test if t->kind in a set */
- error(18L, NULL, NULL, NULL, NULL, false);
- t->kind = kindUNKNOWN;
- t->UNKNOWN.unknm = newname();
- t->UNKNOWN.mustendemp = false;
- t->UNKNOWN.mustconn = false;
- }
- while (t->kind == kindINDIR) t = t->INDIR.tcind;
- switch (t->kind) {
-
- case kindSINGLEARROW:
- satistyp(t->SINGLEARROW.tcarg, false, false);
- satistyp(t->SINGLEARROW.tcres, false, false);
- break;
-
- case kindINT:
- case kindFLOAT:
- case kindSTRING:
- case kindBOOL:
- case kindAPS:
- case kindUNKNOWN:
- case kindEMPTYT:
- case kindBASETY:
- case kindLOC: /* ready */
- break;
-
- case kindSYSTY:
- satistyp(t->SYSTY.syscomp, true, false);
- break;
-
- /* it is not possible that there are nested directions */
- case kindCT:
- satistyp(t->CT.tcfirst, mustconn, false);
- satistyp(t->CT.tcrest, mustconn, true);
- break;
-
- case kindALL:
- error(10L, NULL, NULL, Buildsymbol("satistyp",8L), NULL, false);
- break;
-
- case kindSOME:
- satistyp(t->SOME.tcpart, mustconn, false);
- break;
-
- }
- } /* satistyp */
-
- Local typcrec *writeout(ty)
- typcrec *ty;
- {
- /* move the 'ALL' constructors in ty outward, of course after
- supplying names with an unique instance number, to get the
- result */
- typcrec *tyo;
- nminstrec *locnrd;
-
- wro(ty, 0L, &tyo, &locnrd);
- /* 0 is dummy, because ty has an 'ALL' on the outside */
- satistyp(tyo, false, false);
- return (BuildALL(locnrd, tyo));
- } /* writeout */
-
- Local Void TypSymtoTypAtom(t, locs, btns)
- typ t;
- symbol locs;
- envrec *btns;
- {
- /* the occurrences in t of 'TypSym n' with n bound by
- 'BASETYPE n' are replaced by 'TypAtom n'. This for the
- benefit of tha macro-expander (it needs not find out
- bindings in types now)
- locs: local type variables
- btns: BASETYPE's, TYPEnamings in scope */
- symbol nm;
- typcrec *tc;
- typ nxt;
-
- switch (t->tag) {
-
- case TAGTypSym:
- nm = t->TypSym.sym;
- if (!isin(nm, locs)) {
- tc = lookup(btns, &nm);
- if (tc != NULL) {
- nxt = t->next;
- if (tc->kind != kindINDIR) {
- /* tc is an indir., because of the way extendbtns works */
- error(10L, NULL, NULL, Buildsymbol( "TypSymtoTypAtom1",16L),NULL,false);
- } else {
- if (tc->INDIR.tcind->kind != kindALL) /* added by convtype */
- error(10L, NULL, NULL, Buildsymbol("TypSymtoTypAtom2",16L),NULL,false);
- else {
- if (tc->INDIR.tcind->ALL.tcall->kind == kindBASETY) {
- t->tag = TAGTypAtom;
- t->TypAtom.atomnm = nm;
- t->next = nxt;
- }
- }
- }
- }
- }
- break;
-
- case TAGTypLocal:
- TypSymtoTypAtom(t->TypLocal.loctyp, t->TypLocal.locsyms,
- btns);
- break;
-
- case TAGTypFun:
- TypSymtoTypAtom(t->TypFun.funpar, locs, btns);
- TypSymtoTypAtom(t->TypFun.funres, locs, btns);
- break;
-
- case TAGTypIn:
- TypSymtoTypAtom(t->TypIn.ityp, locs, btns);
- break;
-
- case TAGTypOut:
- TypSymtoTypAtom(t->TypOut.otyp, locs, btns);
- break;
-
- case TAGTypUni:
- TypSymtoTypAtom(t->TypUni.uityp, locs, btns);
- TypSymtoTypAtom(t->TypUni.uotyp, locs, btns);
- break;
-
- case TAGTypNon:
- TypSymtoTypAtom(t->TypNon.nontyp, locs, btns);
- break;
-
- case TAGTypPwr:
- TypSymtoTypAtom(t->TypPwr.pwrtyp, locs, btns);
- break;
-
- case TAGTypProd:
- t = t->TypProd.ptypes;
- while (t != NULL) {
- TypSymtoTypAtom(t, locs, btns);
- t = t->next;
- }
- break;
-
- case TAGTypStar:
- TypSymtoTypAtom(t->TypStar.startyp, locs, btns);
- break;
-
- case TAGTypAtom:
- case TAGTypInt:
- case TAGTypBind:
- case TAGTypFlo:
- case TAGTypString:
- case TAGTypBool:
- case TAGTypAppset: /* ready */
- break;
- }
- } /* TypSymtoTypAtom */
-
- Local Void extendenvloc(elts, btns)
- def elts;
- envrec *btns;
- { /* put types of ATOMs, DEFs and MACROs in curenv, given btns
- for names in the declared types */
- /* ! btns': envptr; btnslist: envlistptr */
- def hel;
- orig oo;
-
- hel = elts;
- /* ! btnslist:=nil */
- while (hel != NULL) {
- if (hel->tag == TAGDefVal)
- { addcopy(hel->DefVal.defval, &nestednames);
- oo = nestednorig;
- nestednorig = hel->DefVal.valorig; /* !' */
- /* ! if hel^.valas^.vtval^.tag=TAGVAtom then btns':=btns
- else begin btns' := extendbtns(..wat bij
- macro?..,btns); appendbtns(btns',btnslist) end
- */
- /* assumption: hel^.valas^.tag=TAGVType */
- update(&curenv, hel->DefVal.defval,
- writeout(convtype(hel->DefVal.valas->VType.vttyp,
- btns, NULL)));
- if (adaptds)
- TypSymtoTypAtom(hel->DefVal.valas->VType.vttyp, NULL, btns);
- nestednorig = oo;
- nestednames = nestednames->next;
- if (hel->DefVal.valas->VType.vtval->tag == TAGVAtom)
- hel->DefVal.valas->VType.vtval->VAtom.atomnm
- = hel->DefVal.defval;
- /* make it point to the same, for making unique */
- } else
- { if (hel->tag == TAGDefTyp && adaptds)
- TypSymtoTypAtom(hel->DefTyp.typas, NULL, btns);
- }
- hel = hel->next;
- }
- } /* extendenvloc */
-
- typedef struct unkrec {
- struct unkrec *next;
- typcrec *unk;
- } unkrec;
-
- /* Local variables for replacelocssome: */
- struct LOC_replacelocssome {
- boolean justcopy;
- nminstrec *alllocnames;
- unkrec *freshlocnames;
- } ;
-
- Local typcrec *freshcopy(t, LINK)
- typcrec *t;
- struct LOC_replacelocssome *LINK;
- { /* replace each LOCname by a fresh name */
- nminstrec *hs;
- unkrec *hn;
-
- while (t->kind == kindINDIR) t = t->INDIR.tcind;
- switch (t->kind) {
-
- case kindLOC:
- if (!LINK->justcopy) {
- hs = LINK->alllocnames;
- hn = LINK->freshlocnames;
- while (!(Equalsymbol(hs->nm, t->LOC.locname) &&
- hs->inst == t->LOC.inst)) {
- hs = hs->next;
- hn = hn->next;
- if (hs==NULL)
- { error(10L, NULL, NULL, Buildsymbol( "freshcopy", 9L), NULL, false);
- return t;
- break; }
- }
- if (hn!=NULL) return hn->unk;
- } else
- return t;
- break;
-
- case kindSINGLEARROW:
- return BuildSINGLEARROW(freshcopy(t->SINGLEARROW.tcarg, LINK),
- freshcopy(t->SINGLEARROW.tcres, LINK));
- break;
-
- case kindSYSTY:
- return BuildSYSTY(t->SYSTY.sysdirs,
- freshcopy(t->SYSTY.syscomp, LINK));
- break;
-
- case kindCT:
- return BuildCT(freshcopy(t->CT.tcfirst, LINK),
- freshcopy(t->CT.tcrest, LINK));
- break;
-
- case kindUNKNOWN:
- if (LINK->justcopy)
- return BuildUNKNOWN(t->UNKNOWN.unknm, t->UNKNOWN.mustendemp,
- t->UNKNOWN.mustconn);
- else
- return BuildUNKNOWN(newname(), t->UNKNOWN.mustendemp,
- t->UNKNOWN.mustconn);
- break;
-
- case kindINT:
- case kindFLOAT:
- case kindBOOL:
- case kindSTRING:
- case kindEMPTYT:
- case kindBASETY:
- case kindAPS:
- return t;
- break;
-
- case kindSOME:
- if (LINK->justcopy)
- return BuildSOME(freshcopy(t->SOME.tcpart, LINK),
- t->SOME.somnr);
- else
- return BuildSOME(freshcopy(t->SOME.tcpart, LINK),
- newname());
- break;
-
- case kindALL: /* should not occur here */
- error(10L, NULL, NULL, Buildsymbol( "freshcopy", 9L), NULL, false);
- return t;
- break;
- }
- } /* freshcopy */
-
- /* Local typcrec *replacelocssome PP((typcrec *t, boolean justcopy_)) */
- Local typcrec *replacelocssome(t, justcopy_)
- typcrec *t;
- boolean justcopy_;
- {
- /* if justcopy_, make a fresh copy of t; otherwise
- if t is a ALL type then replace all LOC names , UNKNOWN and
- SOME numbers by fresh ones, since at each use a new value
- may be used for them */
- struct LOC_replacelocssome V;
- unkrec *hup;
-
- V.justcopy = justcopy_;
- while (t->kind == kindINDIR) t = t->INDIR.tcind;
- if (t->kind == kindALL) /* generate new names */
- { V.alllocnames = t->ALL.locs;
- V.freshlocnames = NULL;
- while (V.alllocnames != NULL)
- { hup = (unkrec *)malloc(sizeof(unkrec));
- hup->unk = BuildUNKNOWN(newname(), false, true);
- hup->next = V.freshlocnames;
- V.freshlocnames = hup;
- V.alllocnames = V.alllocnames->next;
- }
- V.alllocnames = t->ALL.locs;
- return (freshcopy(t->ALL.tcall, &V));
- } else {
- if (V.justcopy)
- return (freshcopy(t, &V));
- else
- return t;
- }
- } /* replacelocssome */
-
- #define forcefptoval(f) new_VMacLambda(f,NULL)
- /* forcefptoval(f) new_VMacLambda(f,NULL):
- forces an fp to look like a val by putting a TAGVMacLambda
- with empty mval field around it */
-
- Local typcrec *typefp(iscon, fmp)
- boolean iscon;
- fp fmp;
- { /* gives type of fp; adds types for names to curenv; type for
- name not overwritten if iscon (is formal connection) */
- typcrec *t1, *t2;
- symbol hn;
- boolean rb;
-
- switch (fmp->tag) {
-
- case TAGFpComp:
- t1 = typefp(iscon, fmp->FpComp.fprest);
- rb = restrictable(true, false, t1, forcefptoval(fmp->FpComp.fprest));
- /* must end in empty */
- return BuildCT(typefp(iscon, fmp->FpComp.fpfirst), t1);
- break;
-
- case TAGFpEmpty:
- return BuildSOME(BuildUNKNOWN(newname(), false, iscon),
- newname());
- break;
-
- /* !! mog. foute inv. als iscon false */
- case TAGFpList:
- if (fmp->FpList.fplist == NULL) {
- return BuildSOME(BuildUNKNOWN(newname(), false, iscon),
- newname());
- /* !! mog. foute inv. als iscon false */
- } else {
- t1 = typefp(iscon, fmp->FpList.fplist);
- t2 = typefp(iscon, new_FpList(fmp->FpList.fplist->next));
- /* t1, t2 used so that name extension numbers are independent of the
- order in which the C implementation evaluates function arguments */
- return BuildCT(t1, t2);
- }
- break;
-
- case TAGFpName:
- if (iscon) {
- hn = fmp->FpName.fpsym;
- t1 = lookup(curenv, &hn);
- if (t1 == NULL) {
- t1 = BuildUNKNOWN(newname(), false, true);
- update(&curenv, hn, t1);
- return t1;
- } else {
- fmp->FpName.fpsym = hn;
- return t1;
- }
- } else {
- t1 = BuildUNKNOWN(newname(), false, false);
- update(&curenv, fmp->FpName.fpsym, t1);
- return t1;
- }
- break;
-
- case TAGFpStr:
- return BuildSTRING();
- break;
-
- case TAGFpInt:
- return BuildINT();
- break;
-
- case TAGFpFlo:
- return BuildFLOAT();
- break;
-
- case TAGFpBool:
- return BuildBOOL();
- break;
- }
- } /* typefp */
-
- Local symbol unusedname()
- { /* delivers string-name not appearing in the Glass volume */
- symbol hs;
-
- hs = Buildsymbol(specstr, 3L);
- addext(hs, newname());
- return hs;
- } /* unusedname */
-
- Local Void addetapar(vl, nm)
- val *vl;
- symbol nm;
- {/* change vl to application of vl to nm (distr. over where,
- cond.) */
- val fnc;
- if ((*vl)->tag == TAGVWhere) {
- addetapar(&(*vl)->VWhere.wval, nm);
- return;
- }
- if ((*vl)->tag == TAGVBuiltin) {
- if (cmp_string((*vl)->VBuiltin.oper, "->")==0) {
- addetapar(&(*vl)->VBuiltin.args->next, nm); /* then br. */
- /* else br. */
- addetapar(&(*vl)->VBuiltin.args->next->next, nm);
- }
- return;
- }
- fnc = (val)malloc(sizeof(*fnc));
- *fnc = **vl;
- fnc->next = NULL;
- (*vl)->tag = TAGVValApply;
- (*vl)->VValApply.avval = fnc;
- (*vl)->VValApply.avpar = new_VSym(new_orig("no_file", 0L), nm);
- } /* addetapar */
-
- Local Void fcnamesuniq(notformcon, par, parnames, ncjustname)
- boolean notformcon;
- fp par;
- symbol *parnames;
- boolean ncjustname;
- {
- /* check if par does not already appear in parnames (error);
- if notformcon add it to parnames
- if notformcon and ncjustname only TAGFpName allowed
- (othw. error) */
- if (notformcon && ncjustname && par->tag != TAGFpName)
- error(19L, NULL, NULL, NULL, NULL, false);
- switch (par->tag) {
-
- case TAGFpComp:
- fcnamesuniq(notformcon,par->FpComp.fpfirst, parnames, false);
- fcnamesuniq(notformcon, par->FpComp.fprest, parnames, false);
- break;
-
- case TAGFpList:
- par = par->FpList.fplist;
- while (par != NULL) {
- fcnamesuniq(notformcon, par, parnames, false);
- par = par->next;
- }
- break;
-
- case TAGFpName:
- if (notformcon)
- addunequal(par->FpName.fpsym, parnames);
- else {
- if (isin(par->FpName.fpsym, *parnames))
- error(9L, NULL, NULL, par->FpName.fpsym, NULL, false);
- }
- break;
-
- case TAGFpEmpty:
- case TAGFpInt:
- case TAGFpBool:
- case TAGFpStr: /* ok */
- break;
- }
- } /* fcnamesuniq */
-
- Local Void supplyapsbrc(vl)
- val vl;
- {
- /* surround vl (with appset type) by appset brackets, if there
- are none. Distributed over conditional and where */
- val hv;
-
- switch (vl->tag) {
-
- case TAGVSysApply:
- case TAGVValApply:
- error(28,NULL,NULL,NULL,vl,true);
- hv = (val)malloc(sizeof(*hv));
- *hv = *vl;
- hv->next = NULL;
- vl->tag = TAGVAppset;
- vl->VAppset.aps = hv;
- break;
-
- case TAGVWhere:
- supplyapsbrc(vl->VWhere.wval);
- break;
-
- case TAGVBuiltin:
- if (cmp_string(vl->VBuiltin.oper, "->")==0) {
- supplyapsbrc(vl->VBuiltin.args->next);
- supplyapsbrc(vl->VBuiltin.args->next->next);
- }
- break;
-
- case TAGVSym:
- case TAGVInt:
- case TAGVFlo:
- case TAGVStr:
- case TAGVBool:
- case TAGVType:
- case TAGVSysLambda: case TAGVSysSigma:
- case TAGVList:
- case TAGVAppset:
- case TAGVAtom:
- case TAGVSyn: /* ready */
- break;
- }
- } /* supplyapsbrc */
-
- boolean seemsadir(vl)
- val vl;
- { /* heuristic to guess if the description was meant to be adirectional */
- string op;
-
- switch (vl->tag) {
- case TAGVSysSigma:
- case TAGVSyn:
- case TAGVAppset:
- return true;
- case TAGVWhere:
- return seemsadir(vl->VWhere.wval);
- case TAGVBuiltin:
- {op = vl->VBuiltin.oper;
- if(cmp_string(op,"->")==0)
- { return ((seemsadir(vl->VBuiltin.args->next)) ||
- (seemsadir(vl->VBuiltin.args->next->next)));
- } else {return false;}
- };
- default:
- return false;
- }
- } /* seemsadir */
-
- Local Void checkbody(dm, ty, btns, isdef, parnames)
- val dm;
- typcrec *ty;
- envrec *btns;
- boolean isdef;
- symbol parnames;
- { /* check if this alternative body dm has the type ty.
- btns: BT/TN holding here
- isdef: only single names allowed as (non-conn.) parameter
- parnames: names for (non-formal connection)parameters
- already encountered */
- symbol nm;
- val rest;
- fp etapar, fmp;
- typcrec *t1, *t2;
- errorrec *err, *errad;
- boolean adok, ado;
-
- while (ty->kind == kindINDIR) ty = ty->INDIR.tcind;
- if (ty->kind == kindSINGLEARROW || ty->kind == kindSYSTY)
- { if (dm->tag != TAGVMacLambda) /* add eta-parameter */
- { nm = unusedname();
- etapar = new_FpName(nm);
- rest = (val)malloc(sizeof(*rest));
- *rest = *dm;
- rest->next = NULL;
- addetapar(&rest, nm);
- dm->tag = TAGVMacLambda;
- dm->VMacLambda.mpar = etapar;
- dm->VMacLambda.mval = rest;
- }
- }
- if (ty->kind == kindSINGLEARROW) /* dm->tag=TAGVMacLambda */
- { fcnamesuniq(true, dm->VMacLambda.mpar, &parnames, isdef);
- compat(typefp(false, dm->VMacLambda.mpar),
- ty->SINGLEARROW.tcarg, forcefptoval(dm->VMacLambda.mpar));
- checkbody(dm->VMacLambda.mval, ty->SINGLEARROW.tcres, btns, isdef,
- parnames);
- return;
- }
- mark_(&curenv);
- if (ty->kind == kindSYSTY) /* dm^.tag=TAGVMacLambda */
- { fcnamesuniq(false, dm->VMacLambda.mpar, &parnames, false);
- ado = adaptds;
- adaptds = false;
- /* to prevent making names unique twice */
- err = errorlist;/* try if can be interpreted adirectionally*/
- t1 = BuildUNKNOWN(newname(),false,true);
- compat(BuildSYSTY(BuildOd(BuildNON()), t1),
- replacelocssome(ty, true), dm);
- /* order: for directionsin the system type */
- compat(typefp(true, dm->VMacLambda.mpar),t1 ,
- forcefptoval(dm->VMacLambda.mpar));
- compat(BuildAPS(),
- typeval(makeadirwanted,dm->VMacLambda.mval,btns,0L),
- dm->VMacLambda.mval);
- adok = (errorlist == err);
- release_(&curenv, false); /* types for conn. names removed */
- adaptds = ado;
- mark_(&curenv);
- errad = errorlist;
- errorlist = err;/* try if can be interpreted unidirectionally */
- t1 = BuildUNKNOWN(newname(),false,true);
- t2 = BuildUNKNOWN(newname(),false,true);
- compat(BuildSYSTY(BuildCd(BuildOd(BuildIN()),
- BuildCd(BuildOd(BuildOUT()), BuildOd(BuildNON()))),
- BuildCT(t1,
- BuildCT(t2,BuildSOME(BuildUNKNOWN(newname(),false,true),newname())))),
- ty, dm);
- compat(typefp(true, dm->VMacLambda.mpar),t1 ,
- forcefptoval(dm->VMacLambda.mpar));
- compat(t2,typeval(makedirwanted,dm->VMacLambda.mval,btns,0L),
- dm->VMacLambda.mval);
- if (adok)
- { if (errorlist == err) /* both adir and dir ok: warning */
- { error(2L, NULL, NULL, NULL, NULL, true);
- if (!takewarning && adaptds)
- { /* TAGVMacLambda fp rest -> TAGVSysLambda fp rest: */
- fmp = dm->VMacLambda.mpar;
- rest = dm->VMacLambda.mval;
- dm->tag = TAGVSysLambda;
- dm->VSysLambda.slpar = fmp;
- dm->VSysLambda.slval = rest;
- }
- } else /* adir. ok, unidir not */
- { errorlist = err;
- supplyapsbrc(dm->VMacLambda.mval);
- if (adaptds)
- { /* TAGVMacLambda fp rest -> TAGVSysSigma fp rest: */
- fmp = dm->VMacLambda.mpar;
- rest = dm->VMacLambda.mval;
- dm->tag = TAGVSysSigma;
- dm->VSysSigma.sspar = fmp;
- dm->VSysSigma.ssval = rest;
- }
- }
- } else
- if (errorlist == err) /* unidir ok, adir not */
- {if (adaptds)
- { /* VMacLambda f r -> VSysLambda f r */
- fmp = dm->VMacLambda.mpar;
- rest = dm->VMacLambda.mval;
- dm->tag = TAGVSysLambda;
- dm->VSysLambda.slpar = fmp;
- dm->VSysLambda.slval = rest;
- }
- } else /* unidir and adir both wrong */
- { if (seemsadir(dm->VMacLambda.mval)) {errorlist = errad;};
- error(3L, NULL, NULL, NULL, NULL, true);
- }
- }
- else
- compat(ty, typeval(makewanted(ty), dm, btns, 0L), dm);
- release_(&curenv, adaptds && uniq); /* remove conn. names */
- } /* checkbody */
-
- Local Void checkdm(dm, ty, btns)
- val dm;
- typcrec *ty;
- envrec *btns;
- { /* check if def/macro dm has required type ty (and some simple checks)
- dm: TAGVMacAlts?is macro; is def
- ty: type of dm, with all local type names in front (ALL)
- btns BT/TNs holding on this level ( ! and local defs) */
- typcrec *typc;
- boolean isdef;
-
- if (dm->tag == TAGVMacAlts) {
- dm = dm->VMacAlts.alts;
- isdef = false;
- } else isdef = true;
- typc = ty;
- while (typc->kind==kindINDIR) typc=typc->INDIR.tcind;
- if (typc->kind!=kindALL)
- {error(10L,NULL,NULL,Buildsymbol("checkdm",7L),NULL,false);
- return;}
- while (dm != NULL) {
- mark_(&curenv); /* before the parameters */
- checkbody(dm, replacelocssome(typc->ALL.tcall, true), btns, isdef, NULL);
- /* replace...: ALL removed, SOME/UNKNOWN numbers renewed,
- so that empty type stays that */
- release_(&curenv, adaptds && uniq);
- dm = dm->next;
- }
- } /* checkdm */
-
- Local Void checkdms(elts, btns)
- def elts;
- envrec *btns;
- { /* check each DEF/MACRO in the elts-list for cont.sens. corr.,
- given btns for names in the declared types */
- def hel;
- /* ! btns': envptr */
- symbol n;
- orig oo;
-
- hel = elts;
- /* ! btns':=btnslist */
- while (hel != NULL) {
- if (hel->tag == TAGDefVal) {
- if (hel->DefVal.valas->VType.vtval->tag != TAGVAtom)
- { /* ass.: hel^.valas^.tag=TAGVType */
- n = hel->DefVal.defval;
- addcopy(n, &nestednames);
- oo = nestednorig;
- nestednorig = hel->DefVal.valorig; /*! slist^.el */
- checkdm(hel->DefVal.valas->VType.vtval, lookup(curenv, &n), btns);
- hel->DefVal.defval = n;
- nestednames = nestednames->next;
- nestednorig = oo;
- /* ! ; btnslist:=btnslist^.next */
- }
- }
- hel = hel->next;
- }
- } /* checkdms */
-
- /* Local variables for typeval: */
- struct LOC_typeval {
- envrec *btns;
- long splitlevel;
- } ;
-
- /* Local variables for typeBuiltin: */
- struct LOC_typeBuiltin {
- typcrec *Result;
- val args;
- typcrec *targ1, *targ2;
- } ;
-
- Local boolean try(ta1, ta2, restype, LINK)
- typcrec *ta1, *ta2, *restype;
- struct LOC_typeBuiltin *LINK;
- {
- /* gives true if targ1 is compatible with ta1; if so checks if
- ta2 (if not nil) is compatible with targ2, and assigns
- restype to typeBuiltin */
- boolean Result;
- errorrec *er;
-
- er = errorlist;
- errorlist = NULL;
- compat(ta1, LINK->targ1, LINK->args);
- Result = (errorlist == NULL);
- if (errorlist != NULL) {
- errorlist = er;
- return Result;
- }
- errorlist = er;
- if (ta2 != NULL)
- compat(ta2, LINK->targ2, LINK->args->next);
- LINK->Result = restype;
- return Result;
- } /* try */
-
- Local typcrec *typeBuiltin(appnon, vl, LINK)
- adirindic appnon;
- val vl;
- struct LOC_typeval *LINK;
- {
- /* deliver type of builtin operator op, with its arguments
- (1, 2 or 3) in args; appnon: application in snd or third arg.
- to be interpreted adirectionally */
- string op;
- struct LOC_typeBuiltin V;
- typcrec *targ3;
- boolean rb;
- long l;
- adirindic apn1, apn2, apn3;
-
- V.args = vl->VBuiltin.args;
- op=vl->VBuiltin.oper;
- if (cmp_string(op,"->")==0) {apn1 = makedirwanted; apn2 = apn3 = appnon;}
- else
- if (cmp_string(op,"[..]")==0) {apn1 = appnon; apn2 = apn3 = makedirwanted;}
- else
- if (cmp_string(op,":")==0) splitwanted(appnon,&apn1,&apn2);
- else apn1 = apn2 = makedirwanted;
- V.targ1 = typeval(apn1, V.args, LINK->btns, LINK->splitlevel);
- if (V.args->next != NULL) {
- V.targ2 = typeval(apn2, V.args->next, LINK->btns, LINK->splitlevel);
- if (V.args->next->next != NULL)
- targ3 = typeval(apn3, V.args->next->next, LINK->btns, LINK->splitlevel);
- }
- else {V.targ2 = NULL;}
- if ((cmp_string(op, "=")==0) | (cmp_string(op, "/=")==0)) {
- if (try(BuildINT(), BuildINT(), BuildBOOL(), &V))
- return V.Result;
- if (try(BuildFLOAT(), BuildFLOAT(), BuildBOOL(), &V))
- return V.Result;
- if (try(BuildBOOL(), BuildBOOL(), BuildBOOL(), &V))
- return V.Result;
- if (!try(BuildSTRING(), BuildSTRING(), BuildBOOL(), &V)) {
- error(6L, V.targ1, V.targ2, NULL, vl, false);
- return (BuildBOOL());
- }
- return V.Result;
- }
- if ((cmp_string(op,"+2")==0) | (cmp_string(op,"*")==0) |
- (cmp_string(op,"-2")==0) | (cmp_string(op,"^")==0) |
- (cmp_string(op,"MOD")==0)) {
- if (try(BuildINT(), BuildINT(), BuildINT(), &V))
- return V.Result;
- if (!try(BuildFLOAT(), BuildFLOAT(), BuildFLOAT(), &V)) {
- error(6L, V.targ1, V.targ2, NULL, vl, false);
- return (BuildUNKNOWN(newname(), false, false));
- }
- return V.Result;
- }
- if (cmp_string(op, "/")==0) {
- if (try(BuildINT(), BuildINT(), BuildFLOAT(), &V))
- return V.Result;
- if (!try(BuildFLOAT(), BuildFLOAT(), BuildFLOAT(), &V)) {
- error(6L, V.targ1,V.targ2, NULL, vl, false);
- return (BuildFLOAT());
- }
- return V.Result;
- }
- if (cmp_string(op,"DIV")==0) {
- if (try(BuildINT(), BuildINT(), BuildINT(), &V))
- return V.Result;
- if (!try(BuildFLOAT(), BuildFLOAT(), BuildINT(), &V)) {
- error(6L, V.targ1,V.targ2, NULL, vl, false);
- return (BuildINT());
- }
- return V.Result;
- }
- if ((cmp_string(op, "<")==0) | (cmp_string(op,"<=")==0) |
- (cmp_string(op,">")==0) | (cmp_string(op,">=")==0)) {
- if (try(BuildINT(), BuildINT(), BuildBOOL(), &V))
- return V.Result;
- if (!try(BuildFLOAT(), BuildFLOAT(), BuildBOOL(), &V)) {
- error(6L, V.targ1, V.targ2, NULL, vl, false);
- return (BuildBOOL());
- }
- return V.Result;
- }
- if ((cmp_string(op,"&")==0) | (cmp_string(op,"|")==0)) {
- if (!try(BuildBOOL(), BuildBOOL(), BuildBOOL(), &V)) {
- error(6L, V.targ1, V.targ2, NULL, vl,false);
- return (BuildBOOL());
- }
- return V.Result;
- }
- if (cmp_string(op,":")==0) {
- rb = restrictable(true, false, V.targ2, V.args->next);
- /* true: must end in empty! */
- return (BuildCT(V.targ1, V.targ2));
- }
- if ((cmp_string(op, "-1")==0) | (cmp_string(op,"+1")==0)) {
- if (try(BuildINT(), NULL, BuildINT(), &V))
- return V.Result;
- if (!try(BuildFLOAT(), NULL, BuildFLOAT(), &V)) {
- error(6L, V.targ1, V.targ2, NULL, vl, false);
- return (BuildUNKNOWN(newname(), false, false));
- }
- return V.Result;
- }
- if (cmp_string(op,"~")==0) {
- if (!try(BuildBOOL(), NULL, BuildBOOL(), &V)) {
- error(6L, V.targ1, V.targ2, NULL, vl, false);
- return (BuildBOOL());
- }
- return V.Result;
- }
- if (cmp_string(op,"->")==0) {
- compat(BuildBOOL(), V.targ1, V.args);
- return (upper(V.targ2, targ3, V.args->next->next));
- /* for the last arg., args^.next could have been taken */
- }
- if (cmp_string(op,"[..]")==0) {
- V.Result = BuildSOME(uppercomps(V.targ1, V.args), newname());
- /* !! this may introduce wrong fill-ins, if uppercomps
- contains UNKNOWN */
- compat(BuildINT(), V.targ2, V.args->next);
- compat(BuildINT(), targ3, V.args->next->next);
- return V.Result;
- }
- if (!cmp_string(op,"itof")==0)
- { l=0; while (op[l]!='\0') l++;
- error(10L, NULL, NULL, Buildsymbol(op,l), NULL, false);
- return (BuildUNKNOWN(newname(), false, false));
- }
- if (!try(BuildINT(), NULL, BuildFLOAT(), &V)) {
- error(6L, V.targ1, V.targ2, NULL, vl, false);
- return (BuildFLOAT());
- }
- return V.Result;
- } /* typeBuiltin */
-
- Local typcrec *typename(n)
- symbol *n;
- {
- /* find type of n in curenv;
- if not there, give it any conn. type */
- typcrec *t;
-
- t = lookup(curenv, n);
- if (t == NULL) {
- t = BuildUNKNOWN(newname(), false, true);
- update(&curenv, *n, t);
- return t;
- } else
- return (replacelocssome(t, false));
- } /* typename */
-
- Local typcrec *typeld(ld, btns, splitlevel)
- def ld;
- envrec *btns;
- long splitlevel;
- {
- /* if ld (appearing in where) is of the form "ns=e" or appset
- then check its type; result type is APS
- btns, splitlevel: same function as in typeval */
- typcrec *t1;
-
- if (ld->tag == TAGDefCon) /* appsets in where not (yet) in d.s. */
- { t1 = BuildUNKNOWN(newname(), false, true);
- compat(t1, typeval(makedirwanted, ld->DefCon.defcon, btns, splitlevel),
- ld->DefCon.defcon);
- compat(t1, typeval(makedirwanted, ld->DefCon.conas, btns, splitlevel),
- ld->DefCon.conas);
- }
- return (BuildAPS());
- } /* typeld */
-
- Local Void splitcurenv(splitlevel, ce, le)
- long splitlevel;
- envrec **ce, **le;
- {
- /* curenv contains:
- conn. names;mark;ADMnames_n;mark;conn.names_n;mark;
- ... ;ADMnames_0; mark; connnames_0; mark;
- explicitly declared names
- ce will contain:
- conn. names;conn. names_n;mark; ... ; ADMnames_0; mark;
- connnames_0; mark; explicitly declared names
- le will contain:
- ADMnames_n;mark;...;ADMnames_0;explicitly declared names
- n = splitlevel
- */
- envrec *h, *h2, *hold;
- long i;
-
- hold = NULL;
- h = curenv;
- while (!ismark(h)) {
- hold = h;
- h = h->next;
- }
- h = h->next;
- *le = h;
- while (!ismark(h))
- h = h->next;
- if (hold == NULL)
- *ce = h->next;
- else {
- *ce = curenv;
- hold->next = h->next;
- }
- hold = h;
- h = h->next;
- for (i = 1; i <= splitlevel; i++) {
- while (!ismark(h))
- h = h->next;
- h = h->next;
- while (!ismark(h)) {
- h2 = (envrec *)malloc(sizeof(envrec));
- *h2 = *h;
- hold->next = h2;
- hold = h2;
- h = h->next;
- }
- }
- while (!ismark(h))
- h = h->next;
- hold->next = h->next;
- } /* splitcurenv */
-
- Local typcrec *typeval(appnon, vl, btns_, splitlevel_)
- adirindic appnon;
- val vl;
- envrec *btns_;
- long splitlevel_;
- {
- /* gives type of vl in type-environment curenv;
- appnon is the appset type: system application taken as adirectional
- btns_: basetypes and typenamings holding in types found in vl
- splitlevel_: nr. of ATO/DEF/MAC typedecl. blockss to be
- selected if creating an environment with only
- explicit declarations */
-
- struct LOC_typeval V;
- typcrec *ta, *tf, *t1, *t2;
- errorrec *er;
- symbol hnm;
- envrec *conenv, *locenv;
- def hl;
- val hv, hv2;
- adirindic appfirst, apprest;
-
- V.btns = btns_;
- V.splitlevel = splitlevel_;
- switch (vl->tag) {
-
- case TAGVValApply:
- tf = typeval(makedirwanted, vl->VValApply.avval, V.btns,V.splitlevel);
- er = errorlist;
- errorlist = NULL;
- t1 = BuildUNKNOWN(newname(), false, false);
- t2 = BuildUNKNOWN(newname(), false, false);
- compat(BuildSINGLEARROW(t1, t2), tf, vl->VValApply.avval);
- if (errorlist == NULL) { /* tf function type */
- errorlist = er;
- compat(t1, typeval(makewanted(t1),vl->VValApply.avpar,V.btns,
- V.splitlevel),
- vl->VValApply.avpar);
- return t2;
- }
- else { /* try if it is a system appl. */
- errorlist = NULL;
- t1 = BuildUNKNOWN(newname(), false, true);
- compat(BuildSYSTY(BuildOd(BuildNON()), t1), tf,vl->VValApply.avval);
- if (errorlist==NULL)
- { /* it IS a system application */
- if (adaptds)
- { /* TAGVValApply s c -> TAGVSysApply s c: */
- hv = vl->VValApply.avval;
- hv2 = vl->VValApply.avpar;
- vl->tag = TAGVSysApply;
- vl->VSysApply.asval = hv;
- vl->VSysApply.aspar = hv2;
- }
- if (adirwanted(appnon))
- { errorlist = er;
- compat(t1, typeval(makedirwanted, vl->VValApply.avpar, V.btns,
- V.splitlevel),
- vl->VValApply.avpar);
- return BuildAPS();
- }
- else /* appnon is not appset type, should be unidir. sys. appl. */
- {t1 = BuildUNKNOWN(newname(), false, true);
- t2 = BuildUNKNOWN(newname(), false, true);
- compat(BuildSYSTY(BuildCd(BuildOd(BuildIN()),
- BuildCd(BuildOd(BuildOUT()),
- BuildOd(BuildNON()))), BuildCT(t1,
- BuildCT(t2,BuildSOME(BuildUNKNOWN(newname(),
- false,
- true),
- newname())))),
- tf, vl->VValApply.avval);
- if (errorlist == NULL) /* tf IS an unidir sys.type */
- { errorlist = er;
- compat(t1,
- typeval(makedirwanted,vl->VValApply.avpar,V.btns, V.splitlevel),
- vl->VValApply.avpar);
- return t2;
- } else
- { errorlist = er;
- error(5L, tf, NULL, NULL, vl->VValApply.avval, false);
- return BuildUNKNOWN(newname(), false, true);
- }
- }
- }
- else
- { errorlist = NULL;
- ta = typeval(makedirwanted,vl->VValApply.avpar,V.btns,V.splitlevel);
- compat (BuildINT(), ta, vl->VValApply.avpar);
- if (errorlist == NULL) /* indexing */
- {errorlist = er;
- if (adaptds)
- { /* TAGVValApply l i -> TAGVBuiltin "[]" [l,i]: */
- hv = vl->VValApply.avval;
- hv2 = vl->VValApply.avpar;
- hv->next = hv2;
- hv2->next = NULL;
- vl->tag = TAGVBuiltin;
- vl->VBuiltin.oper = "[]";
- vl->VBuiltin.args = hv;
- }
- return uppercomps(tf, vl->VValApply.avval);
- } else
- { errorlist = er;
- error(6L, tf, ta, NULL, vl, false);
- return BuildUNKNOWN(newname(), false, false);
- }
- }
- }
- break;
-
- case TAGVSysApply:
- error(10L, NULL, NULL, Buildsymbol( "typeval", 7L), NULL, false);
- return BuildUNKNOWN(newname(), false, false);
- break;
-
- case TAGVSym:
- hnm = vl->VSym.sym;
- t1 = typename(&hnm);
- /* no test anymore if name in fc lud lhs and synonyms wasn't
- declared as something else */
- vl->VSym.sym = hnm;
- return t1;
- break;
-
- case TAGVInt:
- return BuildINT();
- break;
-
- case TAGVFlo:
- return BuildFLOAT();
- break;
-
- case TAGVStr:
- return BuildSTRING();
- break;
-
- case TAGVBool:
- return BuildBOOL();
- break;
-
- case TAGVSysLambda:
- mark_(&curenv);
- mark_(&curenv);
- /* simulate empty block of ATOM/DEF/MAC decls.,
- because splitcurenv assumes at least one A/D/M block */
- splitcurenv(V.splitlevel, &conenv, &locenv);
- curenv = locenv;
- t1 = typefp(true, vl->VSysLambda.slpar);
- t2 = typeval(makedirwanted, vl->VSysLambda.slval, V.btns, 0L);
- if (restrictable(false, true, t1, forcefptoval(vl->VSysLambda.slpar)) &
- restrictable(false, true, t2, vl->VSysLambda.slval))
- ta = BuildSYSTY(BuildCd(BuildOd(BuildIN()),
- BuildCd(BuildOd(BuildOUT()), BuildOd(BuildNON()))),
- BuildCT(t1, BuildCT(t2, BuildSOME(BuildUNKNOWN(newname(),
- false,true),
- newname()))));
- else
- ta = BuildUNKNOWN(newname(), false, false);
- release_(&curenv, adaptds && uniq);
- /* the local connames of this lambda abstr. */
- curenv = conenv;
- return ta;
- break;
-
- case TAGVSysSigma:
- mark_(&curenv);
- mark_(&curenv);
- /* simulate empty block of ATOM/DEF/MAC decls.,
- because splitcurenv assumes at least one A/D/M block */
- splitcurenv(V.splitlevel, &conenv, &locenv);
- curenv = locenv;
- t1 = typefp(true, vl->VSysSigma.sspar);
- er = errorlist;
- compat(BuildAPS(),
- typeval(makeadirwanted, vl->VSysSigma.ssval, V.btns, 0L),
- vl->VSysSigma.ssval);
- if (restrictable(false, true, t1, forcefptoval(vl->VSysSigma.sspar)) &&
- errorlist == er)
- ta = BuildSYSTY(BuildOd(BuildNON()), t1);
- else
- ta = BuildUNKNOWN(newname(), false, false);
- release_(&curenv, adaptds && uniq);
- /* the local connames of this sigma abstr. */
- curenv = conenv;
- return ta;
- break;
-
- case TAGVType: /* does not appear here */
- error(10L, NULL, NULL, Buildsymbol( "typeval", 7L), NULL, false);
- return BuildUNKNOWN(newname(), false, false);
- break;
-
- case TAGVWhere:
- mark_(&curenv); /* after formcons and conn. names */
- mark_(&V.btns);
- V.btns = extendbtns(vl->VWhere.wdefs, V.btns);
- extendenvloc(vl->VWhere.wdefs, V.btns);
- mark_(&curenv); /* after ATOM/DEF/Mac names */
- hl = vl->VWhere.wdefs;
- while (hl != NULL) {
- compat(BuildAPS(),typeld(hl,V.btns,V.splitlevel+1,&V), NULL);
- /* compat always correct, so nil does not matter */
- hl = hl->next;
- }
- ta = typeval(appnon, vl->VWhere.wval, V.btns, V.splitlevel + 1);
- splitcurenv(V.splitlevel, &conenv, &locenv);
- curenv = locenv;
- checkdms(vl->VWhere.wdefs, V.btns);
- release_(&V.btns, adaptds && uniq);
- release_(&curenv, adaptds && uniq);
- /* local ATOM/DEF/MACs removed */
- curenv = conenv;
- return ta;
- break;
-
- case TAGVList:
- if (vl->VList.l == NULL) {
- return BuildSOME(BuildUNKNOWN(newname(), false, false), newname());
- /* !! mog. foute inv. */
- } else {
- splitwanted(appnon,&appfirst,&apprest);
- t1 = typeval(appfirst, vl->VList.l, V.btns, V.splitlevel);
- t2 = typeval(apprest, new_VList(vl->VList.l->next), V.btns, V.splitlevel);
- /* t1, t2 used so that name extension numbers are independent of the
- order in which the C implementation evaluates function arguments */
- return BuildCT(t1,t2);
- }
- break;
-
- case TAGVAppset:
- t1 = BuildAPS();
- hv = vl->VAppset.aps;
- while (hv != NULL) {
- compat(t1, typeval(makeadirwanted,hv,V.btns,V.splitlevel), hv);
- hv = hv->next;
- }
- return t1;
- break;
-
- case TAGVAtom: /* need not be treated here */
- error(10L, NULL, NULL, Buildsymbol( "typeval", 7L), NULL, false);
- return BuildUNKNOWN(newname(), false, false);
- break;
-
- case TAGVSyn:
- t1 = BuildUNKNOWN(newname(), false, true);
- hv = vl->VSyn.synlist;
- while (hv != NULL) {
- compat(t1,typeval(makedirwanted,hv,V.btns,V.splitlevel), hv);
- hv = hv->next;
- }
- return BuildAPS();
- break;
-
- case TAGVBuiltin:
- return typeBuiltin(appnon, vl, &V);
- break;
-
- case TAGVMacLambda:
- /* only encountered when a def/mac has more parameters
- than types for them */
- error(4L, NULL, NULL, NULL, NULL, false);
- t1 =typeval(appnon,vl->VMacLambda.mval,V.btns,V.splitlevel);
- return BuildUNKNOWN(newname(), false, false);
- break;
-
- case TAGVMacAlts: /* need not be treated here */
- error(10L, NULL, NULL, Buildsymbol( "typeval", 7L), NULL, false);
- return BuildUNKNOWN(newname(), false, false);
- break;
- }/* case */
- } /* typeval */
-
- Void checkglasstext(glass)
- def_list glass;
- { /* do simple context-sensitive and typing demand checks for a Glass volume;
- if errors found, deliver errors, otherwise changed data structure */
- envrec *btns;
- _PROCEDURE TEMP;
-
- adaptds = true;
- marker = Buildsymbol("",0L); /* initialisation of a constant */
- errordiscovered = false;
- forfull = true;
- namessupply = 0;
- nestednames = NULL;
- nestednorig = NULL;
- extsupply = 0;
- btns = emptyenv;
- mark_(&btns);
- btns = extendbtns(glass, btns);
- curenv = emptyenv;
- mark_(&curenv);
- extendenvloc(glass, btns);
- checkdms(glass, btns);
- release_(&btns, uniq);
- release_(&curenv, uniq);
- TEMP.proc = (Anyptr)unparsval;
- printerrors(TEMP, errorlist);
- } /* checkglasstext */
-